package com.maimao.search.service;

import cn.hutool.core.convert.Convert;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.StrUtil;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import com.maimao.core.model.charts.OrderAggTimeType;
import com.maimao.core.model.charts.OrderDynamicAggTimeType;
import com.maimao.core.model.resp.PageResult;
import com.maimao.core.utils.DateUtils;
import com.maimao.core.utils.StringUtil;
import com.maimao.model.echarts.common.BarLineOption;
import com.maimao.model.echarts.common.ChartsResult;
import com.maimao.model.echarts.common.EchartsOption;
import com.maimao.model.echarts.common.PieOption;
import com.maimao.model.order.enums.OrderStatus;
import com.maimao.model.order.es.EsOrder;
import com.maimao.model.order.es.EsOrderGoods;
import com.maimao.model.order.es.EsOrderShop;
import com.maimao.model.order.input.OrderSearchInput;
import com.maimao.search.model.goods.EsGoods;
import com.maimao.search.model.goods.SearchPageResult;
import com.maimao.search.utils.EsQueryFieldHandler;
import com.maimao.search.utils.EsUtil;
import lombok.extern.slf4j.Slf4j;
import org.apache.lucene.search.join.ScoreMode;
import org.elasticsearch.action.bulk.BulkRequest;
import org.elasticsearch.action.bulk.BulkResponse;
import org.elasticsearch.action.index.IndexRequest;
import org.elasticsearch.action.search.SearchRequest;
import org.elasticsearch.action.search.SearchResponse;
import org.elasticsearch.client.RequestOptions;
import org.elasticsearch.client.RestHighLevelClient;
import org.elasticsearch.common.unit.TimeValue;
import org.elasticsearch.common.xcontent.XContentType;
import org.elasticsearch.index.query.BoolQueryBuilder;
import org.elasticsearch.index.query.QueryBuilder;
import org.elasticsearch.index.query.QueryBuilders;
import org.elasticsearch.index.query.RangeQueryBuilder;
import org.elasticsearch.search.aggregations.AggregationBuilders;
import org.elasticsearch.search.aggregations.ParsedMultiBucketAggregation;
import org.elasticsearch.search.aggregations.bucket.histogram.DateHistogramAggregationBuilder;
import org.elasticsearch.search.aggregations.bucket.histogram.DateHistogramInterval;
import org.elasticsearch.search.aggregations.bucket.histogram.ExtendedBounds;
import org.elasticsearch.search.aggregations.bucket.histogram.Histogram;
import org.elasticsearch.search.aggregations.bucket.nested.ParsedNested;
import org.elasticsearch.search.aggregations.bucket.terms.ParsedStringTerms;
import org.elasticsearch.search.aggregations.bucket.terms.Terms;
import org.elasticsearch.search.aggregations.bucket.terms.TermsAggregationBuilder;
import org.elasticsearch.search.aggregations.metrics.sum.ParsedSum;
import org.elasticsearch.search.builder.SearchSourceBuilder;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;

import java.io.IOException;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.*;
import java.util.stream.Collectors;

import static cn.hutool.core.date.DatePattern.NORM_DATETIME_MINUTE_PATTERN;
import static cn.hutool.core.util.StrUtil.COMMA;
import static com.maimao.core.constant.Constants.*;

/**
 * @author MaoLin Wang
 * @date 2021/3/29 11:39 下午
 */
@Service
@Slf4j
public class OrderService {
    public static final String FIELD_CREATE_TIME = "createTime";
    @Value("${maimao.es.order.index}")
    private String index;
    @Value("${maimao.es.order.type}")
    private String type;

    @Autowired
    private EsUtil esUtil;

    @Autowired
    private RestHighLevelClient restHighLevelClient;

    /**
     * 订单后台柱状+折线系列名
     */
    private static final String[] ORDER_BAR_LINE_SERIES_NAMES = new String[]{"交易成功", "交易失败", "交易总量", "订单成交总额"};


    /*
    {
          "query": {
            "bool": {
              "must": [
                {
                  "nested": {
                    "path": "orderShopList.orderGoodsList",
                    "query": {
                      "match": {
                        "orderShopList.orderGoodsList.title": "Apple"
                      }

                    },
                    "score_mode": "avg"
                  }
                },
                {
                  "term": {
                    "id": {
                      "value": "5289962234663174152"
                    }
                  }
                }
              ]
            }
          }
        }
     */

    /**
     * 条件筛选订单数据集
     */
    public PageResult<EsOrder> list(OrderSearchInput input, Integer page, Integer size) {
        BoolQueryBuilder boolQueryBuilder = esQueryFieldHandler.handle(input);
        SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder()
                .from((page - 1) * size)
                .size(size)
                .query(boolQueryBuilder);
        SearchRequest searchRequest = new SearchRequest(index)
                .types(type)
                .source(searchSourceBuilder);
        JSONArray jsonArray = new JSONArray();
        SearchResponse searchResponse = esUtil.search(searchRequest, jsonArray);
        List<EsOrder> esOrderList = jsonArray.toJavaList(EsOrder.class);

        return new PageResult<>(esOrderList, searchResponse.getHits().totalHits);
    }


    public boolean saveBatch(List<EsOrder> esOrderList) {

        BulkRequest bulkRequest = new BulkRequest();
        bulkRequest.timeout(TimeValue.MINUS_ONE);
        for (EsOrder esOrder : esOrderList) {
            IndexRequest indexRequest = new IndexRequest(index, type);
            indexRequest.id(esOrder.getId() == null ? null : esOrder.getId());
            indexRequest.source(JSON.toJSONString(esOrder), XContentType.JSON);
            bulkRequest.add(indexRequest);
        }
        BulkResponse bulkRes = null;
        try {
            bulkRes = restHighLevelClient.bulk(bulkRequest, RequestOptions.DEFAULT);
            if (bulkRes.hasFailures()) {
                log.error("批量同步订单失败，失败原因 —— {}", bulkRes.buildFailureMessage());
            } else {
                log.info("批量同步订单成功 {}", bulkRequest.toString());

            }
        } catch (IOException e) {
            log.error("批量同步订单失败，失败原因 —— {}", e.getMessage());
            e.printStackTrace();
        }
        return !bulkRes.hasFailures();

    }

     /*
        饼图查询算法：
            {
          "query": {
            "range": {
              "createTime": {
                "gte": "2021-01-27T10:38:15",
                "lte": "2021-01-28T10:38:15"
              }
            }
          },
          "aggs": {
            "typeAgg": {
              "terms": {
                "field": "status"
              }
            }
          }
        }
     */

    /**
     * 订单饼图
     */
    public ChartsResult<Map<String, Object>> pieCharts(Integer time) {
        LocalDateTime from = OrderAggTimeType.getValueByCode(time);
        String statusAgg = "statusAgg";


        QueryBuilder boolQueryBuilder = ObjectUtil.isNull(from) ? null :
                QueryBuilders.rangeQuery(FIELD_CREATE_TIME).gte(from);

        SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder()
                .query(boolQueryBuilder)
                .aggregation(AggregationBuilders.terms(statusAgg).field("status"));

        SearchRequest searchRequest = getOrderSearchRequest(searchSourceBuilder);
        SearchResponse searchResponse = esUtil.search(searchRequest);
        Map<String, List<ParsedStringTerms.ParsedBucket>> aggStringBuckets = esUtil.getAggStringBuckets(searchResponse);
        List<ParsedStringTerms.ParsedBucket> parsedBuckets = aggStringBuckets.get(statusAgg);

        PieOption<Map<String, Object>> pieOption = new PieOption<>();
        //进行中(commit,paid)、交易成功、交易取消
        pieOption.setLegend(Arrays.asList("进行中", "交易成功", "交易取消"));
        if (ObjectUtil.isNotEmpty(parsedBuckets)) {
            // 状态 -> 数量
            Map<String, Long> statusCountMap = parsedBuckets.stream().collect(Collectors.toMap(ParsedStringTerms.ParsedBucket::getKeyAsString, ParsedMultiBucketAggregation.ParsedBucket::getDocCount));
            List<EchartsOption.SeriesData<Map<String, Object>>> seriesDataList = Lists.newArrayList();

            //进行中的订单数量
            int processingCount = 0;

            EchartsOption.SeriesData<Map<String, Object>> seriesData = new EchartsOption.SeriesData<>();
            seriesData.setName("订单概览");
            List<Map<String, Object>> data = Lists.newArrayListWithCapacity(3);
            Map<String, Object> map = null;
            for (Map.Entry<String, Long> statusCount : statusCountMap.entrySet()) {
                if (Integer.valueOf(statusCount.getKey()).equals(OrderStatus.NOT_PAY.getStatus()) || Integer.valueOf(statusCount.getKey()).equals(OrderStatus.PAID.getStatus())) {
                    //进行中的订单
                    processingCount += statusCount.getValue().intValue();
                } else {
                    //成功或取消的订单

                    map = Maps.newHashMapWithExpectedSize(2);
                    map.put("value", statusCount.getValue());
                    map.put("name", OrderStatus.getMsgByCode(Integer.valueOf(statusCount.getKey())));
                    data.add(map);
                }
            }
            map = Maps.newHashMapWithExpectedSize(2);
            map.put("name", "进行中");
            map.put("value", processingCount);
            data.add(map);
            seriesData.setData(data);
            seriesDataList.add(seriesData);

            pieOption.setSeries(seriesDataList);
        }

        return new ChartsResult<>(pieOption, searchResponse.getHits().totalHits);
    }



    /*
      聚合逻辑：
      1.对订单状态进行聚合；
      2、1的基础上根据创建时间进行 分分钟/分小时/分天/分月/分季度和分年聚合，强制返回null值，指定范围
      3、在2的基础上对orderShopList进行嵌套聚合；
      4、在3的基础上对orderShopList.actualPrice进行求和聚合
         GET /mm_order/_search
                {
                    "size": 0,
                    "query": {
                        "range": {
                            "createTime": {
                                "from": "2020-03-30T23:31:52.152Z",
                                "to": "2021-03-30T23:31:52.152Z",
                                "include_lower": true,
                                "include_upper": true,
                                "boost": 1
                            }
                        }
                    },
                    "aggregations": {
                        "statusAgg": {
                            "terms": {
                                "field": "status",
                                "size": 10,
                                "min_doc_count": 1,
                                "shard_min_doc_count": 0,
                                "show_term_doc_count_error": false,
                                "order": [
                                    {
                                        "_count": "desc"
                                    },
                                    {
                                        "_key": "asc"
                                    }
                                ]
                            },
                            "aggregations": {
                                "timeAgg": {
                                    "date_histogram": {
                                        "field": "createTime",
                                        "format": "8yyyy-MM-dd HH:mm",
                                        "interval": "1M",
                                        "offset": 0,
                                        "order": {
                                            "_key": "asc"
                                        },
                                        "keyed": false,
                                        "min_doc_count": 0,
                                        "extended_bounds": {
                                            "min": "2020-03-30 23:31",
                                            "max": "2021-03-30 23:31"
                                        }
                                    },
                                    "aggregations": {
                                        "nestedAgg": {
                                            "nested": {
                                                "path": "orderShopList"
                                            },
                                            "aggregations": {
                                                "sumAgg": {
                                                    "sum": {
                                                        "field": "orderShopList.actualPrice"
                                                    }
                                                }
                                            }
                                        }
                                    }
                                }
                            }
                        }
                    }
                }
     */

    /**
     * 订单折线+柱状统计 GMV(成交总额)=销售额+取消订单金额+退货订单金额等 即所有订单总额
     * <p>维度：柱状：订单成交量（总量）、 订单交易成功量、 无效量； 折线：订单成交总额（所有订单总额）</p>
     *
     * @param aggTimeType 时间聚合类型
     * @return
     */
    public BarLineOption<List<Object>> dynamicCharts(Integer aggTimeType) {
        final String statusAggName = "statusAgg";
        final String timeAggName = "timeAgg";
        final String nestedAggName = "nestedAgg";
        final String sumAggName = "sumAgg";

        OrderDynamicAggTimeType enumByCode = OrderDynamicAggTimeType.getEnumByCode(aggTimeType);
        int expectedMapSize = enumByCode == null ? 30 : enumByCode.getAggSize();


        // 获取日期聚合和queryBuilder
        LinkedList<Object> histogramAggAndRangeQueryBuilder = getHistogramAggAndRangeQueryBuilder(timeAggName, aggTimeType);
        DateHistogramAggregationBuilder histogramAggregationBuilder = (DateHistogramAggregationBuilder) histogramAggAndRangeQueryBuilder.get(0);
        RangeQueryBuilder rangeQueryBuilder = (RangeQueryBuilder) histogramAggAndRangeQueryBuilder.get(1);

        //terms聚合
        TermsAggregationBuilder aggregation = AggregationBuilders.terms(statusAggName).field(EsOrder.FIELD_STATUS)
                .subAggregation(//日期子聚合
                        histogramAggregationBuilder
                                .subAggregation(
                                        //嵌套子聚合
                                        AggregationBuilders.nested(nestedAggName, EsOrder.FIELD_ORDER_SHOP_LIST)
                                                //求和子聚合
                                                .subAggregation(AggregationBuilders.sum(sumAggName).field(EsOrderShop.FIELD_ACTUAL_PRICE))
                                ));

        SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder();
        searchSourceBuilder.size(0)
                .query(rangeQueryBuilder)
                .aggregation(aggregation);

        SearchRequest searchRequest = getOrderSearchRequest(searchSourceBuilder);
        SearchResponse searchResponse = esUtil.search(searchRequest);

        BarLineOption<List<Object>> barLineOption = new BarLineOption<>();
        String[] split = barLineOption.getSeriesType().split(COMMA);
        String bar = split[0];
        String line = split[1];

        List<EchartsOption.SeriesData<List<Object>>> seriesDataList = Lists.newArrayList();

        List<? extends Terms.Bucket> termsBuckets = ((Terms) searchResponse.getAggregations().get(statusAggName)).getBuckets();

        List<? extends Histogram.Bucket> histogramBuckets = null;

        //有值的系列数量，如果不等于4，则需要填充0值
        int seriesHasDataCount = 0;

        if (ObjectUtil.isNotEmpty(termsBuckets)) {

            //柱状维度： 订单总量=订单成交量(termsBucket.key==5)+进行中(termsBucket.key==1||termsBucket.key==2)+无效(termsBucket.key==6)

            //订单成交总量(柱状)
            EchartsOption.SeriesData<List<Object>> seriesDataBarAll = new EchartsOption.SeriesData<>();
            seriesDataBarAll.setName(ORDER_BAR_LINE_SERIES_NAMES[2]);
            seriesDataBarAll.setYAxisIndex(ZERO);
            seriesDataBarAll.setType(bar);
            Map<String, Integer> orderCountMap = Maps.newLinkedHashMapWithExpectedSize(expectedMapSize);

            //订单成交总额(折线)
            EchartsOption.SeriesData<List<Object>> seriesDataLine = new EchartsOption.SeriesData<>();
            seriesDataLine.setName(ORDER_BAR_LINE_SERIES_NAMES[3]);
            seriesDataLine.setType(line);
            seriesDataLine.setYAxisIndex(ONE);
            Map<String, Double> orderPriceMap = Maps.newLinkedHashMapWithExpectedSize(expectedMapSize);

            for (Terms.Bucket termsBucket : termsBuckets) {

                //每个termBucket是一个系列对象 {"name": '订单成交量',"type": 'bar', "data": dataList }, dataList:[[时间,value]]

                //交易成功和交易失败 —— 柱状
                EchartsOption.SeriesData<List<Object>> seriesDataBar = new EchartsOption.SeriesData<>();

                Integer status = Convert.toInt(termsBucket.getKeyAsString(), null);
                if (status == null) continue;
                if (status.equals(OrderStatus.SUCCESS.getStatus())) {
                    seriesDataBar.setName(ORDER_BAR_LINE_SERIES_NAMES[0]);
                } else if (status.equals(OrderStatus.CANCEL.getStatus())) {
                    seriesDataBar.setName(ORDER_BAR_LINE_SERIES_NAMES[1]);
                }
                boolean processing = status.equals(OrderStatus.NOT_PAY.getStatus()) || status.equals(OrderStatus.PAID.getStatus());
                seriesDataBar.setType(bar);
                seriesDataBar.setYAxisIndex(0);

                //系列data值,结构：[[时间,value]]
                List<List<Object>> barDataList = Lists.newLinkedList();

                List<Object> barData;

                histogramBuckets = ((Histogram) termsBucket.getAggregations().get(timeAggName)).getBuckets();
                for (Histogram.Bucket histogramBucket : histogramBuckets) {

                    orderCountMap.compute(histogramBucket.getKeyAsString(), (k, v) -> {
                        if (v == null) {
                            return Math.toIntExact(histogramBucket.getDocCount());
                        } else {
                            return Math.toIntExact(v + histogramBucket.getDocCount());
                        }
                    });

                    //当前订单总额 求和聚合
                    ParsedNested nested = histogramBucket.getAggregations().get(nestedAggName);
                    final double orderPriceTotal = ((ParsedSum) nested.getAggregations().get(sumAggName)).getValue();

                    orderPriceMap.compute(histogramBucket.getKeyAsString(), (k, v) -> {
                        if (v == null) {
                            return orderPriceTotal;
                        } else {
                            return v + orderPriceTotal;
                        }
                    });

                    //不对进行中的订单数据维度统计
                    if (processing) {
                        continue;
                    }
                    barData = Lists.newLinkedList();
                    //yyyy-MM-dd HH:mm 类型的时间
                    barData.add(histogramBucket.getKeyAsString());
                    barData.add(histogramBucket.getDocCount());
                    System.out.println(histogramBucket.getKeyAsString());
                    System.out.println(histogramBucket.getKey());


                    seriesHasDataCount++;
                    barDataList.add(barData);


                }
                //不对进行中的订单数据维度统计
                if (processing) {
                    continue;
                }
                seriesDataBar.setData(barDataList);
                seriesDataList.add(seriesDataBar);

            }

            List<List<Object>> seriesDataBarAllDataList = Lists.newLinkedList();
            List<Object> seriesDataBarAllData;
            for (Map.Entry<String, Integer> entry : orderCountMap.entrySet()) {
                seriesDataBarAllData = Lists.newLinkedList();
                seriesDataBarAllData.add(entry.getKey());
                seriesDataBarAllData.add(entry.getValue());
                seriesDataBarAllDataList.add(seriesDataBarAllData);
                seriesHasDataCount++;
            }
            seriesDataBarAll.setData(seriesDataBarAllDataList);

            List<List<Object>> seriesDataLineDataList = Lists.newLinkedList();
            List<Object> seriesDataLineData;
            for (Map.Entry<String, Double> entry : orderPriceMap.entrySet()) {
                seriesDataLineData = Lists.newLinkedList();
                seriesDataLineData.add(entry.getKey());
                seriesDataLineData.add(entry.getValue());
                seriesDataLineDataList.add(seriesDataLineData);
                seriesHasDataCount++;
            }

            seriesDataLine.setData(seriesDataLineDataList);

            seriesDataList.add(seriesDataBarAll);
            seriesDataList.add(seriesDataLine);
        }

        // 有值的 系列个数不为4，则填充0
        if (seriesHasDataCount != ORDER_BAR_LINE_SERIES_NAMES.length) {
            fillEmpty(seriesDataList, timeAggName, histogramBuckets, histogramAggregationBuilder, rangeQueryBuilder);
        }
        barLineOption.setSeries(seriesDataList);

        return barLineOption;

    }

    /**
     * 如果某个系列没有值的话 填充0值
     *
     * @param seriesDataList 系列Data对象List
     * @param buckets        时间聚合桶
     */
    private void fillEmpty(List<EchartsOption.SeriesData<List<Object>>> seriesDataList, String timeAggName, List<? extends Histogram.Bucket> buckets, DateHistogramAggregationBuilder histogramAggregationBuilder, RangeQueryBuilder rangeQueryBuilder) {
        if (ObjectUtil.isEmpty(buckets)) {

            // 全部为空，说明此时间段没有任何订单数据，再次根据时间聚合获取时间聚合桶
            SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder().aggregation(histogramAggregationBuilder).query(rangeQueryBuilder).size(0);
            SearchRequest searchRequest = getOrderSearchRequest(searchSourceBuilder);
            SearchResponse response = esUtil.search(searchRequest);

            buckets = ((Histogram) response.getAggregations().get(timeAggName)).getBuckets();
        }

        // 每个系列查到的Optional选项List
        List<Optional<EchartsOption.SeriesData<List<Object>>>> seriesOptions = Lists.newLinkedList();
        seriesOptions.add(seriesDataList.stream().filter(item -> item.getName().equals(ORDER_BAR_LINE_SERIES_NAMES[0])).findFirst());
        seriesOptions.add(seriesDataList.stream().filter(item -> item.getName().equals(ORDER_BAR_LINE_SERIES_NAMES[1])).findFirst());
        seriesOptions.add(seriesDataList.stream().filter(item -> item.getName().equals(ORDER_BAR_LINE_SERIES_NAMES[2])).findFirst());
        seriesOptions.add(seriesDataList.stream().filter(item -> item.getName().equals(ORDER_BAR_LINE_SERIES_NAMES[3])).findFirst());

        // 生成0值 不设置name和type了，前端直接写死
        EchartsOption.SeriesData<List<Object>> seriesDataEmpty = new EchartsOption.SeriesData<>();
        List<List<Object>> emptyDataList = Lists.newLinkedList();
        List<Object> emptyData;
        for (Histogram.Bucket bucket : buckets) {
            bucket.getKeyAsString();
            emptyData = Lists.newLinkedList();
            emptyData.add(bucket.getKeyAsString());
            emptyData.add(0);
            emptyDataList.add(emptyData);
        }
        seriesDataEmpty.setData(emptyDataList);

        // 对没有值的系列填充0值
        for (int i = 0; i < seriesOptions.size(); i++) {
            if (!seriesOptions.get(i).isPresent()) {
                seriesDataList.add(i, seriesDataEmpty);
            }
        }

    }

    /**
     * 根据聚合时间类型获取 DateHistogramAggregationBuilder和范围查询
     *
     * @param aggName     聚合名
     * @param aggTimeType 聚合时间类型
     * @return LinkedList [DateHistogramAggregationBuilder,RangeQueryBuilder]
     */
    private LinkedList<Object> getHistogramAggAndRangeQueryBuilder(String aggName, Integer aggTimeType) {
        List<Object> dateIntervalExtendBoundsList = getDateIntervalAndExtendedBounds(aggTimeType);
        DateHistogramAggregationBuilder dateHistogramAggregationBuilder = AggregationBuilders.dateHistogram(aggName)
                .field(EsOrder.FIELD_CREATE_TIME)
                .format("8yyyy-MM-dd HH:mm")
                .dateHistogramInterval((DateHistogramInterval) dateIntervalExtendBoundsList.get(0))
                .minDocCount(0)
                .extendedBounds((ExtendedBounds) dateIntervalExtendBoundsList.get(1));
        LinkedList<Object> hisAggAndRangeQueryList = Lists.newLinkedList();
        hisAggAndRangeQueryList.add(dateHistogramAggregationBuilder);
        hisAggAndRangeQueryList.add(dateIntervalExtendBoundsList.get(2));
        return hisAggAndRangeQueryList;
    }

    /**
     * 根据聚合时间类型获取DateHistogramInterval类型、extendedBounds和日期范围查询builder
     *
     * @param aggTimeType 聚合时间类型 默认取HOUR
     * @return LinkedList [DateHistogramInterval,ExtendedBounds,RangeQueryBuilder]
     */
    private List<Object> getDateIntervalAndExtendedBounds(Integer aggTimeType) {
        List<Object> dateIntervalExtendBoundsList = Lists.newLinkedList();
        RangeQueryBuilder rangeQueryBuilder = QueryBuilders.rangeQuery(EsOrder.FIELD_CREATE_TIME);
        LocalDateTime now = DateUtils.now();
        final DateTimeFormatter formatter = DateTimeFormatter.ofPattern(NORM_DATETIME_MINUTE_PATTERN);

        String min = "";
        String max = now.format(formatter);
        LocalDateTime from;

        if (aggTimeType.equals(OrderDynamicAggTimeType.MINUTE.getCode())) {

            dateIntervalExtendBoundsList.add(DateHistogramInterval.MINUTE);
            from = now.plusHours(-1);

        } else if (aggTimeType.equals(OrderDynamicAggTimeType.HOUR.getCode())) {

            dateIntervalExtendBoundsList.add(DateHistogramInterval.HOUR);
            from = now.plusHours(-24);

        } else if (aggTimeType.equals(OrderDynamicAggTimeType.DAY.getCode())) {

            dateIntervalExtendBoundsList.add(DateHistogramInterval.DAY);
            from = now.plusDays(-30);

        } else if (aggTimeType.equals(OrderDynamicAggTimeType.MONTH.getCode())) {

            dateIntervalExtendBoundsList.add(DateHistogramInterval.MONTH);
            from = now.plusYears(-1);

        } else if (aggTimeType.equals(OrderDynamicAggTimeType.QUARTER.getCode())) {

            dateIntervalExtendBoundsList.add(DateHistogramInterval.QUARTER);
            from = DateUtils.firstDayOfYear();
            max = DateUtils.lastDayOfYear().format(formatter);

        } else if (aggTimeType.equals(OrderDynamicAggTimeType.YEAR.getCode())) {

            dateIntervalExtendBoundsList.add(DateHistogramInterval.YEAR);
            from = DateUtils.firstDayOfYear().plusYears(-5);

        } else {
            dateIntervalExtendBoundsList.add(DateHistogramInterval.HOUR);
            from = now.plusHours(-24);
        }

        rangeQueryBuilder.gte(from).lte(now);
        min = from.format(formatter);
        //指定强制返回的时间聚合范围
        ExtendedBounds extendedBounds = new ExtendedBounds(min, max);
        dateIntervalExtendBoundsList.add(extendedBounds);
        dateIntervalExtendBoundsList.add(rangeQueryBuilder);
        return dateIntervalExtendBoundsList;
    }

    private SearchRequest getOrderSearchRequest(SearchSourceBuilder searchSourceBuilder) {
        return new SearchRequest(new String[]{index}, searchSourceBuilder)
                .types(type);
    }

    @Autowired
    private EsQueryFieldHandler esQueryFieldHandler;
}
